{
 "cells": [
  {
   "cell_type": "markdown",
   "source": [
    "# Using ZhipuAI GLM-4 though OpenAI SDK and Ecosystem\n",
    "\n",
    "**This tutorial is available in English and is attached below the Chinese explanation**\n",
    "\n",
    "本节代码将带领大家使用`OpenAI`的 SDK 和支持的框架调用 `GLM-4` 模型\n",
    "你将在本章节学习到如何使用 Langchain 的 `ChatOpenAI` 类来调用 ZhipuAI 的 GLM-4 模型，以及如何使用 `OpenAI SDK` 类来实现调用GLM-4模型。\n",
    "\n",
    "This notebook section will walk you through calling `GLM-4` models using the `OpenAI` SDK and supporting frameworks.\n",
    "In this section you will learn how to call ZhipuAI's GLM-4 models using Langchain's `ChatOpenAI` class, and how to use the `OpenAI SDK` class to implement calling GLM-4 models.\n"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "91a626e20197e21c"
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 1. Use OpenAI SDK\n",
    "\n",
    "首先，需要导入 `OpenAI` SDK，同时，修改 `OpenAI` 的 `base_url` 为 `https://open.bigmodel.cn/api/paas/v4/` \n",
    "以便调用 `GLM-4` 模型。完成更换后，仅需填写 Key 就能使用 `GLM-4` 模型。\n",
    "\n",
    "First, you need to import the `OpenAI` SDK and change the `OpenAI` `base_url` to `https://open.bigmodel.cn/api/paas/v4/` in order to call the `GLM-4` model. \n",
    "in order to call the `GLM-4` model. Once you have done this, you can use the `GLM-4` model by simply filling in the Key.\n",
    "``python"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "b58e7836f5b885b6"
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "from openai import OpenAI\n",
    "\n",
    "client = OpenAI(\n",
    "    api_key=\"your api key\",\n",
    "    base_url=\"https://open.bigmodel.cn/api/paas/v4/\")"
   ],
   "metadata": {
    "collapsed": true,
    "ExecuteTime": {
     "end_time": "2024-04-28T06:57:23.098964Z",
     "start_time": "2024-04-28T06:57:22.825376Z"
    }
   },
   "id": "initial_id",
   "execution_count": 2
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 2. Simple use of OpenAI SDK to call GLM-4\n",
    "\n",
    "我将带领大家完成最基础的对话调用。\n",
    "请注意：\n",
    "- `temperature` 参数的区间为 (0,1)。\n",
    "- `do_sample = False (temperature = 0)` 在 OpenAI 调用中并不适用。\n",
    "-  异步操作不适用。\n",
    "\n",
    "其他例子(例如工具调用)，也均可以按照OpenAI的方式进行调用。\n",
    "\n",
    "\n",
    "I will lead everyone to complete the most basic dialogue calls.\n",
    "Please note:\n",
    "\n",
    "- The interval of the `temperature` parameter is (0,1).\n",
    "- `do_sample=False (temperature=0)` is not applicable in OpenAI calls.\n",
    "- Asynchronous operations are not applicable.\n",
    "\n",
    "Other examples (such as tool calls) can also be called in the same way as OpenAI."
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "11e3e2b3eddb8819"
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "data": {
      "text/plain": "ChatCompletion(id='8605595589064489203', choices=[Choice(finish_reason='stop', index=0, logprobs=None, message=ChatCompletionMessage(content=\"Sure! Here's a light-hearted joke for you:\\n\\nWhy don't scientists trust atoms?\\n\\nBecause they make up everything! 😄\", role='assistant', function_call=None, tool_calls=None))], created=1714287444, model='glm-4', object=None, system_fingerprint=None, usage=CompletionUsage(completion_tokens=28, prompt_tokens=9, total_tokens=37), request_id='8605595589064489203')"
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "response = client.chat.completions.create(\n",
    "    model=\"glm-4\",\n",
    "    messages=[\n",
    "        {\n",
    "            \"role\": \"user\",\n",
    "            \"content\": \"tell me a joke\"\n",
    "        }\n",
    "    ],\n",
    "    top_p=0.7,\n",
    "    temperature=0.9,\n",
    "    stream=False,\n",
    "    max_tokens=2000,\n",
    ")\n",
    "response"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-04-28T06:57:24.278985Z",
     "start_time": "2024-04-28T06:57:23.100145Z"
    }
   },
   "id": "46b558c16e324725",
   "execution_count": 3
  },
  {
   "cell_type": "markdown",
   "source": [],
   "metadata": {
    "collapsed": false
   },
   "id": "e96faeabc4754841"
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 3. Using Langchain's ChatOpenAI class\n",
    "\n",
    "Langchain 的 `ChatOpenAI` 类是对 `OpenAI` SDK 的封装，可以更方便调用。这里展示了如何使用 `ChatOpenAI` 类来调用 `GLM-4` 模型。\n",
    "\n",
    "Langchain's `ChatOpenAI` class is a wrapper around the `OpenAI` SDK, making it easier to call. Here we show how to use the `ChatOpenAI` class to call the `GLM-4` model."
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "ba894923a1806fc2"
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/zr/Code/glm-cookbook/venv/lib/python3.9/site-packages/urllib3/__init__.py:35: NotOpenSSLWarning: urllib3 v2 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with 'LibreSSL 2.8.3'. See: https://github.com/urllib3/urllib3/issues/3020\n",
      "  warnings.warn(\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001B[1m> Entering new LLMChain chain...\u001B[0m\n",
      "Prompt after formatting:\n",
      "\u001B[32;1m\u001B[1;3mSystem: You are a nice chatbot having a conversation with a human.\n",
      "Human: tell me a joke\u001B[0m\n",
      "\n",
      "\u001B[1m> Finished chain.\u001B[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": "{'question': 'tell me a joke',\n 'chat_history': [HumanMessage(content='tell me a joke'),\n  AIMessage(content=\"Why don't scientists trust atoms?\\n\\nBecause they make up everything! 😄\")],\n 'text': \"Why don't scientists trust atoms?\\n\\nBecause they make up everything! 😄\"}"
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import os\n",
    "from langchain_openai import ChatOpenAI\n",
    "from langchain.prompts import (\n",
    "    ChatPromptTemplate,\n",
    "    MessagesPlaceholder,\n",
    "    SystemMessagePromptTemplate,\n",
    "    HumanMessagePromptTemplate,\n",
    ")\n",
    "from langchain.chains import LLMChain\n",
    "from langchain.memory import ConversationBufferMemory\n",
    "\n",
    "llm = ChatOpenAI(\n",
    "    temperature=0.95,\n",
    "    model=\"glm-4\",\n",
    "    openai_api_key=\"your api key\",\n",
    "    openai_api_base=\"https://open.bigmodel.cn/api/paas/v4/\"\n",
    ")\n",
    "prompt = ChatPromptTemplate(\n",
    "    messages=[\n",
    "        SystemMessagePromptTemplate.from_template(\n",
    "            \"You are a nice chatbot having a conversation with a human.\"\n",
    "        ),\n",
    "        MessagesPlaceholder(variable_name=\"chat_history\"),\n",
    "        HumanMessagePromptTemplate.from_template(\"{question}\")\n",
    "    ]\n",
    ")\n",
    "\n",
    "memory = ConversationBufferMemory(memory_key=\"chat_history\", return_messages=True)\n",
    "conversation = LLMChain(\n",
    "    llm=llm,\n",
    "    prompt=prompt,\n",
    "    verbose=True,\n",
    "    memory=memory\n",
    ")\n",
    "conversation.invoke({\"question\": \"tell me a joke\"})"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-04-28T06:57:25.768169Z",
     "start_time": "2024-04-28T06:57:24.280308Z"
    }
   },
   "id": "95ca98869dcb246a",
   "execution_count": 4
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 4. Calling GLM-4 with LangChain AgentExecutor\n",
    "同时，GLM-4也能很好的接入到 LangChain 的 AgentExecutor 中，这里展示了如何使用 `AgentExecutor` 来调用 `GLM-4` 模型。\n",
    "\n",
    "GLM-4 also plugs nicely into LangChain's AgentExecutor, which shows how to call a `GLM-4` model using `AgentExecutor`."
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "2c6c560191f25ec5"
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001B[1m> Entering new AgentExecutor chain...\u001B[0m\n",
      "\u001B[32;1m\u001B[1;3mTo answer this question, I should use a search engine to gather information about LangChain. Since it's a topic I'm not very familiar with, comprehensive and accurate results would be beneficial.\n",
      "\n",
      "Action: tavily_search_results_json\n",
      "Action Input: What is LangChain?\n",
      "Observation\u001B[0m\u001B[36;1m\u001B[1;3m[{'url': 'https://python.langchain.com/docs/get_started/introduction/', 'content': \"Introduction. LangChain is a framework for developing applications powered by large language models (LLMs). LangChain simplifies every stage of the LLM application lifecycle: Development: Build your applications using LangChain's open-source building blocks and components. Hit the ground running using third-party integrations and Templates.\"}, {'url': 'https://python.langchain.com/docs/modules/agents/concepts/', 'content': 'Note that observation is currently left as type Any to be maximally flexible. In practice, this is often a string. ... LangChain provides a wide set of built-in tools, but also makes it easy to define your own (including custom descriptions). For a full list of built-in tools, see the tools integrations section.'}]\u001B[0m\u001B[32;1m\u001B[1;3mBased on the search results, LangChain is a framework designed to simplify the development of applications using large language models (LLMs). It provides a set of open-source building blocks, components, and templates to help developers create and integrate these applications more effectively.\n",
      "\n",
      "Final Answer: LangChain is a framework that aids in the development of applications using large language models by offering open-source building blocks, components, and templates to streamline the process.\u001B[0m\n",
      "\n",
      "\u001B[1m> Finished chain.\u001B[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": "{'input': 'what is LangChain?',\n 'output': 'LangChain is a framework that aids in the development of applications using large language models by offering open-source building blocks, components, and templates to streamline the process.'}"
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain import hub\n",
    "from langchain.agents import AgentExecutor, create_react_agent\n",
    "from langchain_community.tools.tavily_search import TavilySearchResults\n",
    "\n",
    "os.environ[\"TAVILY_API_KEY\"] = \"your tavily api key\"\n",
    "tools = [TavilySearchResults(max_results=2)]\n",
    "prompt = hub.pull(\"hwchase17/react\")\n",
    "# Choose the LLM to use\n",
    "agent = create_react_agent(llm, tools, prompt)\n",
    "agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)\n",
    "agent_executor.invoke({\"input\": \"what is LangChain?\"})"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-04-28T06:57:40.979933Z",
     "start_time": "2024-04-28T06:57:25.770494Z"
    }
   },
   "id": "4db6cc6154c30560",
   "execution_count": 5
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 5. Using OpenAI SDK to call CogView-3\n",
    "\n",
    "我们也支持使用OpenAI接口调用 `CogView-3` 模型，这里展示了如何使用 `OpenAI SDK` 类来调用 `CogView-3` 模型。但是，仍然有很多参数是无法使用的。\n",
    "\n",
    "We also support using the OpenAI interface to call the `CogView-3` model. Here we show how to use the `OpenAI SDK` class to call the `CogView-3` model. However, there are still many parameters that cannot be used."
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "1e97ddd5dc94a835"
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "data": {
      "text/plain": "ImagesResponse(created=1714287461, data=[Image(b64_json=None, revised_prompt=None, url='https://sfile.chatglm.cn/testpath/7020b0f4-cbbb-562c-8196-576122d6c167_0.png')])"
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "response_cogview = client.images.generate(\n",
    "    model=\"cogview-3\",\n",
    "    prompt=\"一个城市在水晶瓶中的场景\",\n",
    "\n",
    "    # these parameters are not available\n",
    "    # n=2,\n",
    "    # response_format=\"base64\",\n",
    "    # size=\"medium\",\n",
    "    # style=\"natural\",\n",
    "    # quality=\"hd\",\n",
    ")\n",
    "response_cogview"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-04-28T06:57:47.763543Z",
     "start_time": "2024-04-28T06:57:40.981620Z"
    }
   },
   "id": "3dbf6ed4664787ab",
   "execution_count": 6
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "data": {
      "text/html": "<img src=\"https://sfile.chatglm.cn/testpath/7020b0f4-cbbb-562c-8196-576122d6c167_0.png\"/>",
      "text/plain": "<IPython.core.display.Image object>"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from IPython.display import display, Image\n",
    "\n",
    "display(Image(url=response_cogview.data[0].url))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-04-28T06:57:47.770819Z",
     "start_time": "2024-04-28T06:57:47.765737Z"
    }
   },
   "id": "5eafdb66dbd53a2e",
   "execution_count": 7
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 6. UsingOpenAI SDK to call Embedding Model\n",
    "\n",
    "我们也支持使用openAI接口调用 `Embedding` 模型，这里展示了如何使用 `OpenAI SDK` 类来调用 `Embedding` 模型。\n",
    "\n",
    "请注意，`Embedding` 模型的输入暂不支持使用 列表，只能使用字符串。在这里，我仅仅展示了前10个值。\n",
    "\n",
    "We also support using the OpenAI interface to call the `Embedding` model. Here we show how to use the `OpenAI SDK` class to call the `Embedding` model.\n",
    "\n",
    "Please note that the input of the `Embedding` model does not currently support lists and can only be used as strings. Here, I only show the first 10 values."
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "6f7153f26a657e6e"
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "data": {
      "text/plain": "[-0.02675454691052437,\n 0.019060475751757622,\n 0.006672845687717199,\n -0.023301372304558754,\n 0.0015068714274093509,\n -0.04486510157585144,\n -0.04257429763674736,\n -0.006881380919367075,\n 0.04148220270872116,\n 0.06300002336502075]"
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "response_embedding = client.embeddings.create(\n",
    "    model=\"embedding-2\",\n",
    "    input=\"你好\",\n",
    "    \n",
    "    # these parameters are not available\n",
    "    # input=[\"你好\", \"你是谁\"],\n",
    "    # dimensions=1024,\n",
    "    # encoding_format=\"float\",\n",
    ")\n",
    "response_embedding.data[0].embedding[:10] # only show the first 10"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-04-28T06:57:48.212602Z",
     "start_time": "2024-04-28T06:57:47.772564Z"
    }
   },
   "id": "eece9d4c277f639c",
   "execution_count": 8
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
